﻿using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.DgnEC;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeoCoordinates;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using CheccCoverplateCulvertAssemble.Entity;
using CheccCoverplateCulvertAssemble.Tools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CIMNETSolid = Bentley.CIMNET.CIMGeometry.Solid;
using CheccCoverplateCulvertAssemble.Rebar;
using CheccCoverplateCulvertAssemble.Conmmon;
using static Bentley.CIMNET.CIMGeometry.Solid.SolidUtil.Modify;
using Aspose.Cells;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
using CheccTexturePropertyGive;
using static CheccTexturePropertyGive.SetCoverCulvertTexture;
using CheccCoverplateCulvertAssemble.Common;

namespace CheccCoverplateCulvertAssemble.Operation
{
    public class UnitaryBasic : ConstructingEntity
    {
        RebarEntity rebarEntity;
        public UnitaryBasic(BasicConstructor basicConstructor, RebarEntity rebarEntity, CulvertType culvertType, ConstructionMethod constructionMethod, CulvertComponentType culvertComponentType) : base(basicConstructor, culvertType, constructionMethod, culvertComponentType)
        {
            this.rebarEntity = rebarEntity;
        }

        public override void CreateEntityModel()
        {
            var objParameter = GetUorCoverParameter();
            DPoint3d[] points =
            {
                new DPoint3d(0,(objParameter.clearSpan / 2 + objParameter.standPly),0)* GeneralBank.UorToMeters,
                new DPoint3d(0,(objParameter.clearSpan / 2 + objParameter.standPly) ,-(objParameter.piecePly + objParameter.clearHeight)) * GeneralBank.UorToMeters,
                new DPoint3d(0,(objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge),-(objParameter.piecePly + objParameter.clearHeight))* GeneralBank.UorToMeters,
                new DPoint3d(0,(objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge),-(objParameter.piecePly + objParameter.clearHeight + objParameter.basicsPly)) * GeneralBank.UorToMeters,
                new DPoint3d(0,-(objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge),-(objParameter.piecePly + objParameter.clearHeight + objParameter.basicsPly)) * GeneralBank.UorToMeters,
                new DPoint3d(0,-(objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge),-(objParameter.piecePly + objParameter.clearHeight)) * GeneralBank.UorToMeters,
                new DPoint3d(0,-(objParameter.clearSpan / 2 + objParameter.standPly),-(objParameter.piecePly + objParameter.clearHeight)) * GeneralBank.UorToMeters,
                new DPoint3d(0,-(objParameter.clearSpan / 2 + objParameter.standPly),0) * GeneralBank.UorToMeters,

                new DPoint3d(0,-(objParameter.clearSpan / 2 + objParameter.standPly - objParameter.standTopWidth),0) * GeneralBank.UorToMeters,
                new DPoint3d(0, -(objParameter.clearSpan / 2 + objParameter.standPly - objParameter.standTopWidth),-objParameter.piecePly) * GeneralBank.UorToMeters,
                new DPoint3d(0, -(objParameter.clearSpan / 2) ,-objParameter.piecePly)* GeneralBank.UorToMeters,
                new DPoint3d(0, -(objParameter.clearSpan / 2),-(objParameter.piecePly + objParameter.clearHeight - objParameter.bottomChamfer))* GeneralBank.UorToMeters,
                new DPoint3d(0, -(objParameter.clearSpan / 2 - objParameter.bottomChamfer),-(objParameter.piecePly + objParameter.clearHeight)) * GeneralBank.UorToMeters,
                new DPoint3d(0, (objParameter.clearSpan / 2 - objParameter.bottomChamfer),-(objParameter.piecePly + objParameter.clearHeight)) * GeneralBank.UorToMeters,
                new DPoint3d(0,objParameter.clearSpan / 2,-(objParameter.piecePly + objParameter.clearHeight - objParameter.bottomChamfer)) * GeneralBank.UorToMeters,
                new DPoint3d(0, objParameter.clearSpan / 2 ,-objParameter.piecePly) * GeneralBank.UorToMeters,
                new DPoint3d(0, (objParameter.clearSpan / 2 + objParameter.standPly - objParameter.standTopWidth),-objParameter.piecePly )* GeneralBank.UorToMeters,
                new DPoint3d(0, (objParameter.clearSpan / 2 + objParameter.standPly - objParameter.standTopWidth),0) * GeneralBank.UorToMeters,
                new DPoint3d(0,(objParameter.clearSpan / 2 + objParameter.standPly),0) * GeneralBank.UorToMeters,
            };
            ShapeElement shapeElement = new ShapeElement(GeneralBank.ActiveDgnModel, null, points);
            CurveVector secCur = shapeElement.GetCurveVector();
            //涵长扣除城墙缝宽度
            double realLength = objParameter.culvertGapWidth;

            LineElement lineElement = GetSlopLinee(DPoint3d.Zero, objParameter.basicsLength - realLength, objParameter.baseSlope,out DPoint3d slopeEndPT);
            CurveVector linePath = lineElement.GetCurveVector();
            SolidKernelEntity solidKernel = CreateBodyFromSweep(linePath, secCur, GeneralBank.ActiveDgnModel);

            double culvertLen = distanceFromStart + objParameter.culvertGapWidth / 2;
            double z = culvertLen * objParameter.baseSlope;
            DPoint3d movePoint3d = new DPoint3d(culvertLen, 0, z) * GeneralBank.UorToMeters;
            DTransform3d trans = DTransform3d.Identity;
            trans.Translation = movePoint3d;
            TransformBody(ref solidKernel, trans);
            Convert1.BodyToElement(out Element cutResultElement, solidKernel, null, GeneralBank.ActiveDgnModel);
            //cutResultElement.AddToModel();
            //真实位置
            DTransform3d dTransform = new DTransform3d(this.dMatrix3D);
            dTransform.Translation = this.placeDpoint3d * GeneralBank.UorToMeters;
            TransformInfo dTransFormInfo = new TransformInfo(dTransform);
            cutResultElement.ApplyTransform(dTransFormInfo);
            cutResultElement.AddToModel();
            CommonData.Instance.ElementIds.Add(cutResultElement.ElementId.ToString());

            //属性赋予
            SetCoverCulvertECProperty setCoverCulvertECProperty = new SetCoverCulvertECProperty();
            setCoverCulvertECProperty.SetWallECProperty(
                new List<Element> { cutResultElement },
                objParameter.basicsLength.ToString(),
                (objParameter.piecePly + objParameter.clearHeight + objParameter.basicsPly).ToString(),
                objParameter.standTopWidth.ToString(),
                (objParameter.standPly * 2 + objParameter.clearSpan + objParameter.basicsEdge * 2).ToString(),
                objParameter.bottomChamfer.ToString(),
                "",
                ""
                );
            //材质赋予
            SetCoverCulvertTexture setCoverCulvertTexture = new SetCoverCulvertTexture();
            setCoverCulvertTexture.CoverCulvertTexture(cutResultElement, CoverCulvertConstruction.WallBody);

            //创建钢筋实体
            if (this.RebarList.Any())
            {
                foreach (var rebar in this.RebarList)
                {
                    Element rebarElement = rebar.CreateEntityModel();
                    rebarElement.ApplyTransform(dTransFormInfo);
                    rebarElement.AddToModel();
                    rebar.AddElmentMaterial(rebarElement);
                    CommonData.Instance.ElementIds.Add(rebarElement.ElementId.ToString());
                }
            }
        }


        /// <summary>
        /// 基于dPoint3D点沿X轴绘制线
        /// </summary>
        /// <param name="boxCulvertLength">涵长水平距离</param>
        /// <param name="slop">坡度; (例如0.1就是10%的坡率)</param>
        /// <returns></returns>
        public LineElement GetSlopLinee(DPoint3d dPoint3D, double boxCulvertLength, double slop,out DPoint3d endPt)
        {
            double z = boxCulvertLength * slop ;
            endPt = new DPoint3d(dPoint3D.X + boxCulvertLength, dPoint3D.Y, dPoint3D.Z + z) * GeneralBank.UorToMeters;
            return new LineElement(GeneralBank.ActiveDgnModel, null, new DSegment3d(dPoint3D * GeneralBank.UorToMeters , new DPoint3d(dPoint3D.X +boxCulvertLength, dPoint3D.Y, dPoint3D.Z +z) *GeneralBank.UorToMeters));
        }

        public override List<RebarBase> CreateRebarList()
        {
            List<RebarBase> rebarList = new();
            if (this.rebarEntity.dgv_Rebar1.Count == 0) return rebarList;
            rebarList.AddRange(this.CreateRebarListNum1());
            rebarList.AddRange(this.CreateRebarListNum2());
            rebarList.AddRange(this.CreateRebarListNum3());
            rebarList.AddRange(this.CreateRebarListNum4());
            rebarList.AddRange(this.CreateRebarListNum5());
            if (this.rebarEntity.dgv_Rebar6.Count > 0)
            {
                rebarList.AddRange(this.CreateRebarListNum6());
            }
            return rebarList;
        }

        /// <summary>
        /// 获取整体式洞身构造参数
        /// </summary>
        /// <returns> 涵长,左偏角,右偏角,涵身沉降缝宽度,基础沉降缝宽度,涵底坡度, 净跨,净高,挡块高度,基础襟边,台身厚度,台身顶宽,底部倒角,基础厚度,净保护层</returns>
        /// 
        private (double basicsLength, double leftLateralAngle,double rightLateralAngle, double culvertGapWidth,double baseGapWidth, double baseSlope, double clearSpan, double clearHeight, 
            double piecePly, double basicsEdge, double standPly, double standTopWidth, double bottomChamfer, double basicsPly, double protectiveLayer) GetUorCoverParameter()
        {
            double basicsLength = this.basicConstructor.BasicsLength / 100;
            double leftLateralAngle = this.basicConstructor.LeftLateralAngle;
            double rightLateralAngle = this.basicConstructor.RightLateralAngle;
            double culvertGapWidth = this.basicConstructor.CulvertGapWidth / 100;
            double baseGapWidth = this.basicConstructor.BaseGapWidth / 100;
            double baseSlope = this.basicConstructor.CulvertBaseSlope / 100;
            double clearSpan = this.basicConstructor.ClearSpan;
            double clearHeight = this.basicConstructor.ClearHeight;
            double piecePly = this.basicConstructor.PiecePly / 100;
            double basicsEdge = this.basicConstructor.BasicsEdge / 100;
            double standPly = this.basicConstructor.StandPly / 100;
            double standTopWidth = this.basicConstructor.StandTopWidth / 100;
            double bottomChamfer = this.basicConstructor.BottomChamfer / 100;
            double basicsPly = this.basicConstructor.BasicsPly / 100;
            double protectiveLayer = this.basicConstructor.ProtectiveLayer;
            return (basicsLength,leftLateralAngle, rightLateralAngle, culvertGapWidth, baseGapWidth, baseSlope, clearSpan, clearHeight, piecePly, basicsEdge, standPly, standTopWidth, bottomChamfer, basicsPly, protectiveLayer);
        }

        /// <summary>
        /// 获取1#钢筋集合
        /// </summary>
        /// <returns></returns>
        private List<RebarBase> CreateRebarListNum1()
        {
            List<RebarBase> rebarList = new();
            var objParameter = GetUorCoverParameter();
            var rebar1 = this.GetRebarParametersOfNum1();
            //摆放长度
            double putLength = objParameter.clearSpan + objParameter.standPly *2 + objParameter.basicsEdge * 2 - rebar1.edgeDistance * 2;
            //钢筋长度
            double rebar1Length = objParameter.basicsLength - objParameter.protectiveLayer * 2 - objParameter.culvertGapWidth;
            //摆放间距
            double putDistance = putLength / (rebar1.rebarRoot-1);
            //距原点Z偏移长度
            double offsetZ = (distanceFromStart +  objParameter.culvertGapWidth /2  + objParameter.protectiveLayer) * objParameter.baseSlope;
            //摆放起点  X轴  ：钢筋边距 + 距起点长度
            DPoint3d staPoint = new DPoint3d(distanceFromStart + objParameter.culvertGapWidth/2 + objParameter.protectiveLayer,
                (objParameter.clearSpan/2 + objParameter.standPly +objParameter.basicsEdge - rebar1.edgeDistance), 
                -(objParameter.piecePly + objParameter.clearHeight + objParameter.protectiveLayer + rebar1.diameter/1000 / 2)+ offsetZ);
            for (int i = 0; i < rebar1.rebarRoot; i++)
            {
                LineElement lineElement = GetSlopLinee(new DPoint3d(staPoint.X ,staPoint.Y- putDistance * i, staPoint.Z), rebar1Length, objParameter.baseSlope, out DPoint3d pt);
                RebarBase rebarBase1 = new RebarNoHook(this, "1", rebar1.diameter, rebar1.rebarGrade, RebarType.NoRibbed, lineElement.GetCurveVector());
                rebarList.Add(rebarBase1);
            }
            return rebarList;
        }

        /// <summary>
        /// 获取2#钢筋集合
        /// </summary>
        /// <returns></returns>
        private List<RebarBase> CreateRebarListNum2()
        {
            List<RebarBase> rebarList = new();
            double rebar6_diameter = 0;
            if (this.rebarEntity.dgv_Rebar6.Count > 0)
            {
                rebar6_diameter = Convert.ToDouble(this.rebarEntity.dgv_Rebar6[3]);
            }
            var objParameter = GetUorCoverParameter();
            var rebar1 = this.GetRebarParametersOfNum1();
            var rebar2 = this.GetRebarParametersOfNum2();
            //摆放长度
            double putLength = objParameter.basicsLength - objParameter.culvertGapWidth - objParameter.protectiveLayer * 2 - rebar2.diameter / 1000;
            //摆放间距
            double putDistance =1.0/(rebar2.rebarRoot - 1);
            //摆放根数
            int root = (int)Math.Floor(putLength / putDistance) + 1;

            double staX = distanceFromStart + objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer + rebar2.diameter / 1000 / 2;
            double staY = objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge - objParameter.protectiveLayer - rebar2.diameter / 1000 / 2;
            double staZ = objParameter.piecePly + objParameter.clearHeight + objParameter.protectiveLayer + rebar1.diameter / 1000 + rebar6_diameter / 1000 + rebar2.diameter / 1000 / 2;
            for (int i = 0; i < root; i++)
            {   //距原点Z偏移长度
                double offsetZ = (staX + putDistance *i) * objParameter.baseSlope;
                List<DPoint3d> points = new List<DPoint3d>();
                //points.Add(new DPoint3d(staX + putDistance * i, staY, -(staZ + rebar2.hookLength + -offsetZ)) * GeneralBank.UorToMeters);
                points.Add(new DPoint3d(staX + putDistance * i,staY, -(staZ + -offsetZ)) * GeneralBank.UorToMeters);
                points.Add(new DPoint3d(staX + putDistance * i, -staY, -(staZ + -offsetZ)) * GeneralBank.UorToMeters);
                //points.Add(new DPoint3d(staX + putDistance * i, -staY,  -(staZ + rebar2.hookLength + -offsetZ)) * GeneralBank.UorToMeters);
                LineStringElement lineStringElement = new LineStringElement(GeneralBank.ActiveDgnModel, null, points.ToArray());
                //RebarBase rebarBase2 = new RebarNoHook(this, "2", rebar2.diameter, rebar2.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector());
                RebarBase rebarBase2 = new Rebar_90Degrees(this, "2", rebar2.diameter, rebar2.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector(), rebar2.hookLength, rebar2.diameter * 5, 90, 90);
                rebarList.Add(rebarBase2);  
            }
            return rebarList;
        }

        /// <summary>
        /// 获取3#钢筋集合
        /// </summary>
        /// <returns></returns>
        private List<RebarBase> CreateRebarListNum3()
        {
            //横纵都采用净保护层
            List<RebarBase> rebarList = new();
            var objParameter = GetUorCoverParameter();
            var rebar2 = this.GetRebarParametersOfNum2();
            var rebar3 = this.GetRebarParametersOfNum3();
            //摆放间距
            double putDistance  = 1.0 /(int)(rebar3.rebarRoot / 2 -1);
            //摆放长度
            double putLength = objParameter.basicsLength - objParameter.culvertGapWidth - objParameter.protectiveLayer * 2 - rebar3.diameter / 1000;
            //单侧摆放根数
            int num =  (int)Math.Floor(putLength / putDistance) + 1;

            double staX = distanceFromStart + objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer + rebar2.diameter / 1000 + rebar3.diameter / 1000 / 2;
            double staY = objParameter.clearSpan / 2 + objParameter.standPly  - objParameter.protectiveLayer - rebar3.diameter / 1000 / 2;
            double staZ = objParameter.piecePly + objParameter.clearHeight + rebar3.rebarPlaceDepth;
            for (int i = 0; i < num; i++)
            {
                double offsetZ = (staX + putDistance * i) * objParameter.baseSlope;
                LineElement lineElement = new LineElement(GeneralBank.ActiveDgnModel, null, 
                    new DSegment3d(new DPoint3d(staX + putDistance * i,staY, -staZ + offsetZ) * GeneralBank.UorToMeters,
                                    new DPoint3d(staX + putDistance * i, staY, -staZ + offsetZ + rebar3.rebarLength ) * GeneralBank.UorToMeters));
                RebarBase rebarBase3 = new RebarNoHook(this, "3", rebar3.diameter, rebar3.rebarGrade, RebarType.NoRibbed, lineElement.GetCurveVector());
                rebarList.Add(rebarBase3);
            }

            for (int i = 0; i < num; i++)
            {
                double offsetZ = (staX + putDistance * i) * objParameter.baseSlope;
                LineElement lineElement = new LineElement(GeneralBank.ActiveDgnModel, null,
                    new DSegment3d(new DPoint3d(staX + putDistance * i, -staY, -staZ + offsetZ) * GeneralBank.UorToMeters,
                                    new DPoint3d(staX + putDistance * i, -staY, -staZ + offsetZ + rebar3.rebarLength) * GeneralBank.UorToMeters));
                RebarBase rebarBase3 = new RebarNoHook(this, "3", rebar3.diameter, rebar3.rebarGrade, RebarType.NoRibbed, lineElement.GetCurveVector());
                rebarList.Add(rebarBase3);
            }
            return rebarList;
        }
        /// <summary>
        /// 获取4#钢筋集合
        /// </summary>
        /// <returns></returns>
        private List<RebarBase> CreateRebarListNum4()
        {
            /*****四号钢筋布置方式*****
             * 纵向间距：从中间往外布置，剩余长度大于0.5m补充一根
             * 横向间距：从中间往外布置，剩余长度大于0.5m补充一根
             */
            List<RebarBase> rebarList = new();
            double rebar6_diameter = 0;
            if (this.rebarEntity.dgv_Rebar6.Count > 0)
            {
                rebar6_diameter = Convert.ToDouble(this.rebarEntity.dgv_Rebar6[3]);
            }
            var objParameter = GetUorCoverParameter();
            var rebar1 = this.GetRebarParametersOfNum1();
            var rebar2 = this.GetRebarParametersOfNum2();
            var rebar4 = this.GetRebarParametersOfNum4();
            //钢筋长度
            double rebarLength = objParameter.basicsPly - (objParameter.protectiveLayer * 2 + rebar1.diameter / 1000 + rebar6_diameter / 1000 + rebar2.diameter / 1000 + rebar4.diameter / 1000);
            
            //单侧摆放长度Y轴
            double putLengthY = objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge - objParameter.protectiveLayer - rebar2.diameter / 1000 - rebar4.diameter / 1000 /2 - rebar4.distanceY / 2;
            //单侧摆放根数Y轴
            int numY = (int)Math.Floor(putLengthY / rebar4.distanceY) + 1;
            if (putLengthY - rebar4.distanceY * (numY - 1) > 0.5) numY += 1;

            //单侧摆放长度X轴
            double putLengthX = objParameter.basicsLength / 2  - (objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer + rebar2.diameter / 1000 + rebar4.diameter / 1000 / 2 + rebar4.distanceX / 2);
            int numX = (int)Math.Floor(putLengthX / rebar4.distanceX) + 1;
            if (putLengthX - rebar4.distanceX * (numX - 1) > 0.5) numX += 1;

            //double staX = distanceFromStart + objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer + rebar2.diameter / 1000 + rebar4.diameter / 1000 / 2;
            double staX = distanceFromStart + objParameter.basicsLength / 2 + rebar4.distanceX / 2;
            double staY = rebar4.distanceY / 2;
            double staZ = objParameter.piecePly + objParameter.clearHeight + objParameter.protectiveLayer + 
                rebar1.diameter / 1000 + rebar6_diameter / 1000 + rebar2.diameter / 1000 + rebar4.diameter / 1000 / 2;
            //断面左侧、平面右侧
            for (int j = 0; j < numX; j++)
            {
                double ptX = j == numX - 1 ? staX + putLengthX : staX + rebar4.distanceX * j;
                double offsetZ = ptX * objParameter.baseSlope;
                for (int i = 0; i < numY; i++)
                {
                    double ptY = i == numY - 1 ? staY + putLengthY : staY + rebar4.distanceY * i;
                    List<DPoint3d> points = new List<DPoint3d>();
                    //points.Add(new DPoint3d(ptX, ptY - rebar4.hookLength, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    //points.Add(new DPoint3d(ptX, ptY - rebar4.hookLength, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    LineStringElement lineStringElement = new LineStringElement(GeneralBank.ActiveDgnModel, null, points.ToArray());
                    //RebarBase rebarBase4 = new RebarNoHook(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector());
                    RebarBase rebarBase4 = new Rebar_90Degrees(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector(), rebar4.hookLength, rebar4.diameter * 5, -90, -90);
                    rebarList.Add(rebarBase4);
                }
                for (int i = 0; i < numY; i++)
                {
                    double ptY = i == numY - 1 ? -staY - putLengthY : -staY - rebar4.distanceY * i;
                    List<DPoint3d> points = new List<DPoint3d>();
                    //points.Add(new DPoint3d(ptX, ptY + rebar4.hookLength, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    //points.Add(new DPoint3d(ptX, ptY + rebar4.hookLength, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    LineStringElement lineStringElement = new LineStringElement(GeneralBank.ActiveDgnModel, null, points.ToArray());
                    //RebarBase rebarBase4 = new RebarNoHook(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector());
                    RebarBase rebarBase4 = new Rebar_90Degrees(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector(), rebar4.hookLength, rebar4.diameter * 5, 90, 90);
                    rebarList.Add(rebarBase4);
                }
            }
            staX = distanceFromStart + objParameter.basicsLength / 2 - rebar4.distanceX / 2;
            //断面右侧侧、平面左侧
            for (int j = 0; j < numX; j++)
            {
                double ptX = j == numX - 1 ? staX - putLengthX : staX - rebar4.distanceX * j;
                double offsetZ = ptX * objParameter.baseSlope;
                for (int i = 0; i < numY; i++)
                {
                    double ptY = i == numY - 1 ? staY + putLengthY : staY + rebar4.distanceY * i;
                    List<DPoint3d> points = new List<DPoint3d>();
                    //points.Add(new DPoint3d(ptX, ptY - rebar4.hookLength, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    //points.Add(new DPoint3d(ptX, ptY - rebar4.hookLength, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    LineStringElement lineStringElement = new LineStringElement(GeneralBank.ActiveDgnModel, null, points.ToArray());
                    //RebarBase rebarBase4 = new RebarNoHook(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector());
                    RebarBase rebarBase4 = new Rebar_90Degrees(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector(), rebar4.hookLength, rebar4.diameter * 5, -90, -90);
                    rebarList.Add(rebarBase4);
                }
                for (int i = 0; i < numY; i++)
                {
                    double ptY = i == numY - 1 ? -staY - putLengthY : -staY - rebar4.distanceY * i;
                    List<DPoint3d> points = new List<DPoint3d>();
                    //points.Add(new DPoint3d(ptX, ptY + rebar4.hookLength, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -staZ + offsetZ) * GeneralBank.UorToMeters);
                    points.Add(new DPoint3d(ptX, ptY, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    //points.Add(new DPoint3d(ptX, ptY + rebar4.hookLength, -(staZ + rebarLength) + offsetZ) * GeneralBank.UorToMeters);
                    LineStringElement lineStringElement = new LineStringElement(GeneralBank.ActiveDgnModel, null, points.ToArray());
                    //RebarBase rebarBase4 = new RebarNoHook(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector());
                    RebarBase rebarBase4 = new Rebar_90Degrees(this, "4", rebar4.diameter, rebar4.rebarGrade, RebarType.NoRibbed, lineStringElement.GetCurveVector(), rebar4.hookLength, rebar4.diameter * 5, 90, 90);
                    rebarList.Add(rebarBase4);
                }
            }
            return rebarList;
        }


        private List<RebarBase> CreateRebarListNum5()
        {
            List<RebarBase> rebarList = new();
            var objParameter = GetUorCoverParameter();
            var rebar3 = this.GetRebarParametersOfNum3();
            var rebar5 = this.GetRebarParametersOfNum5();

            //单侧摆放根数
            int num = (int)(rebar5.rebarRoot / 2);
            //5号钢筋长度
            double rebarLength = objParameter.basicsLength - objParameter.culvertGapWidth - objParameter.protectiveLayer * 2; 
            double staX = distanceFromStart + objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer;
            double staY = objParameter.clearSpan / 2 + objParameter.standPly - objParameter.protectiveLayer - rebar3.diameter / 1000  - rebar5.diameter / 1000 / 2;
            double staZ = objParameter.piecePly + objParameter.clearHeight + rebar3.rebarPlaceDepth - rebar3.rebarLength + rebar5.diameter /1000 / 2;
            //距原点Z偏移长度
            double offsetZ = staX * objParameter.baseSlope;
            //摆放起点  X轴  ：钢筋边距 + 距起点长度
            DPoint3d staPointL = new DPoint3d(staX, staY, -staZ + offsetZ);
            DPoint3d staPointR = new DPoint3d(staX, -staY, -staZ + offsetZ);
            for (int i = 0; i < num; i++)
            {
                LineElement lineElementL = GetSlopLinee(new DPoint3d(staPointL.X, staPointL.Y, staPointL.Z - rebar5.rebarInterval * i), rebarLength, objParameter.baseSlope, out DPoint3d pt1);
                RebarBase rebarBase5L = new RebarNoHook(this, "5", rebar5.diameter, rebar5.rebarGrade, RebarType.NoRibbed, lineElementL.GetCurveVector());
                rebarList.Add(rebarBase5L);

                LineElement lineElementR = GetSlopLinee(new DPoint3d(staPointL.X, -staPointL.Y, staPointL.Z - rebar5.rebarInterval * i), rebarLength, objParameter.baseSlope, out DPoint3d pt2);
                RebarBase rebarBase5R = new RebarNoHook(this, "5", rebar5.diameter, rebar5.rebarGrade, RebarType.NoRibbed, lineElementR.GetCurveVector());
                rebarList.Add(rebarBase5R);
            }
            return rebarList;

        }

        private List<RebarBase> CreateRebarListNum6()
        {
            List<RebarBase> rebarList = new();
            var objParameter = GetUorCoverParameter();
            var rebar1 = this.GetRebarParametersOfNum1();
            var rebar6 = this.GetRebarParametersOfNum6();

            //摆放长度
            double putLength = objParameter.basicsLength - objParameter.culvertGapWidth - objParameter.protectiveLayer * 2 - rebar6.diameter / 1000;
            //摆放间距
            double putDistance = 1.0 / (rebar6.rebarRoot - 1);
            //摆放根数
            int root = (int)Math.Floor(putLength / putDistance) + 1;

            double staX = distanceFromStart + objParameter.culvertGapWidth / 2 + objParameter.protectiveLayer + rebar6.diameter / 1000 / 2;
            double staY = objParameter.clearSpan / 2 + objParameter.standPly + objParameter.basicsEdge - objParameter.protectiveLayer - rebar6.diameter / 1000 / 2;
            double staZ = objParameter.piecePly + objParameter.clearHeight + objParameter.protectiveLayer + rebar1.diameter / 1000 + rebar6.diameter / 1000 / 2;
            for (int i = 0; i < root; i++)
            {   //距原点Z偏移长度
                double offsetZ = (staX + putDistance * i) * objParameter.baseSlope;
                LineElement lineElement = new LineElement(GeneralBank.ActiveDgnModel, null, new DSegment3d(
                    new DPoint3d(staX + putDistance * i, staY,-staZ + offsetZ) * GeneralBank.UorToMeters,
                    new DPoint3d(staX + putDistance * i, -staY, -staZ + offsetZ) * GeneralBank.UorToMeters));
                RebarBase rebarBase2 = new RebarNoHook(this, "6", rebar6.diameter, rebar6.rebarGrade, RebarType.NoRibbed, lineElement.GetCurveVector());
                rebarList.Add(rebarBase2);
            }
            return rebarList;
        }

        /// <summary>
        /// 获取1#钢筋构造参数
        /// </summary>
        /// <returns>边距,钢筋根数,等级,直径</returns>
        private (double edgeDistance, int rebarRoot, string rebarGrade, double diameter) GetRebarParametersOfNum1()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar1;
            var edgeDistance = Convert.ToDouble(dgvOfRebar[0]) / 100;
            var rebarRoot = Convert.ToInt16(dgvOfRebar[1]);
            var rebarGrade = Convert.ToString(dgvOfRebar[2]);
            var diameter = Convert.ToDouble(dgvOfRebar[3]);
            return (edgeDistance, rebarRoot, rebarGrade, diameter);
        }
        /// <summary>
        /// 获取2#钢筋构造参数
        /// </summary>
        /// <returns>边距,钢筋每延米根数,直径,等级,弯钩长度</returns>
        private (double edgeDistance, int rebarRoot, double diameter, string rebarGrade, double hookLength) GetRebarParametersOfNum2()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar2;
            var edgeDistance = Convert.ToDouble(dgvOfRebar[0]) / 100;
            var rebarRoot = Convert.ToInt16(dgvOfRebar[1]);
            var diameter = Convert.ToDouble(dgvOfRebar[2]);
            var rebarGrade = Convert.ToString(dgvOfRebar[3]);
            var hookLength = Convert.ToDouble(dgvOfRebar[4]);
            return (edgeDistance, rebarRoot, diameter, rebarGrade, hookLength);
        }

        /// <summary>
        /// 获取3#钢筋构造参数
        /// </summary>
        /// <returns>插入基础深度,钢筋每延米根数(双侧),钢筋等级,钢筋总长</returns>
        private (double rebarPlaceDepth, int rebarRoot, string rebarGrade, double diameter, double rebarLength) GetRebarParametersOfNum3()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar3;
            var rebarPlaceDepth = Convert.ToDouble(dgvOfRebar[0]) / 100;
            var rebarRoot = Convert.ToInt16(dgvOfRebar[1]);
            var rebarGrade = Convert.ToString(dgvOfRebar[2]);
            var diameter = Convert.ToDouble(dgvOfRebar[3]);
            var rebarLength = Convert.ToDouble(dgvOfRebar[4]) / 100;
            return (rebarPlaceDepth, rebarRoot, rebarGrade, diameter, rebarLength);
        }

        /// <summary>
        /// 获取4#钢筋构造参数
        /// </summary>
        /// <returns>水平间距,垂直间距,钢筋等级,钢筋直径,弯钩长度</returns>
        private (double distanceX, double distanceY, string rebarGrade, double diameter, double hookLength) GetRebarParametersOfNum4()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar4;
            string[] edges = dgvOfRebar[0].ToString().Split('x');
            var distanceX = Convert.ToDouble(edges[0]) / 100;
            var distanceY = Convert.ToDouble(edges[1]) / 100;
            var rebarGrade = Convert.ToString(dgvOfRebar[1]);
            var diameter = Convert.ToDouble(dgvOfRebar[2]);
            var hookLength = Convert.ToDouble(dgvOfRebar[3]);
            return (distanceX, distanceY, rebarGrade, diameter, hookLength);
        }

        /// <summary>
        /// 获取5#钢筋构造参数
        /// </summary>
        /// <returns>同侧间距,钢筋等级,钢筋直径,钢筋个数</returns>
        private (double rebarInterval, string rebarGrade, double diameter, int rebarRoot) GetRebarParametersOfNum5()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar5;
            var rebarInterval = Convert.ToDouble(dgvOfRebar[0]) / 100;
            var rebarGrade = Convert.ToString(dgvOfRebar[1]);
            var diameter = Convert.ToDouble(dgvOfRebar[2]);
            var rebarRoot = Convert.ToInt16(dgvOfRebar[3]);
            return (rebarInterval, rebarGrade, diameter, rebarRoot);
        }

        /// <summary>
        /// 获取6#钢筋构造参数
        /// </summary>
        /// <returns>同侧间距,钢筋等级,钢筋直径,钢筋个数</returns>
        private (double edgeDistance, string rebarGrade, int rebarRoot, double diameter) GetRebarParametersOfNum6()
        {
            var dgvOfRebar = this.rebarEntity.dgv_Rebar6;
            var rebarInterval = Convert.ToDouble(dgvOfRebar[0]);
            var rebarGrade = Convert.ToString(dgvOfRebar[1]);
            var rebarRoot = Convert.ToInt16(dgvOfRebar[2]);
            var diameter = Convert.ToDouble(dgvOfRebar[3]);
            return (rebarInterval, rebarGrade, rebarRoot, diameter);
        }

        public SolidKernelEntity CreateBodyFromSweep(CurveVector pathCur, CurveVector secCur, DgnModel modelRef)
        {
            pathCur.GetStartEnd(out DPoint3d startPt, out _, out DVector3d startTangent, out _);
            CurveVector secCur1 = secCur.Clone();
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entity, secCur1, pathCur, modelRef, false, true, false, null, null, null, null);
            return entity;
        }

        public static SolidKernelEntity CreateBodyFromExtrusion(CurveVector secCur, double extrusionLength, DPoint3d centroid, DVector3d extrudDir, DgnModel modelRef)
        {
            BentleyStatus status = CIMNETSolid.SolidUtil.Create.BodyFromExtrusion(
                out SolidKernelEntity entity, secCur, extrusionLength, modelRef, extrudDir, false, null);
            return entity;
        }

        public override void CreateElementECProperty(Element element, List<Tuple<string, CustomProperty.TypeKind, bool, bool>> tuples)
        {
            throw new NotImplementedException();
        }

        public override void SetECInstanceValue(IDgnECInstance dgnECInstance, List<(string propertyName, string calculationBasis, string computationalFormula)> propertyData)
        {
            throw new NotImplementedException();
        }

        public override List<(string standardName, string standValue)> CreateStandardECProperty()
        {
            throw new NotImplementedException();
        }

        public override void SaveStandardECProperty(IDgnECInstance dgnECInstance)
        {
            var retJObject = new JObject();
            foreach (var item in this.CreateStandardECProperty())
            {
                retJObject[item.standardName] = item.standValue;
            }

            // 属性赋值
            IEnumerable<IECProperty> eCProperties = dgnECInstance.ClassDefinition.Properties(true);
            foreach (IECProperty eCProperty in eCProperties)
            {
                if (eCProperty.DisplayLabel.Equals("CoverHiddenData"))
                {
                    IECPropertyValue eCPropertyValue =
                        dgnECInstance.FindPropertyValue(eCProperty.Name, false, false, false, false);
                    if (eCPropertyValue != null)
                    {
                        var saveStr = retJObject.ToString(Newtonsoft.Json.Formatting.None);
                        dgnECInstance.SetValue<string>(eCProperty.Name, saveStr);
                    }
                }
            }

            dgnECInstance.ScheduleChanges(dgnECInstance.Element);
            dgnECInstance.Element.ReplaceInModel(dgnECInstance.Element);
        }

        public override double GetVolumeOfElement(Element element)
        {
            double ret = 0.0;
            var instCol = DgnECManager.Manager.GetElementProperties(element, ECQueryProcessFlags.SearchAllClasses);
            foreach (var inst in instCol)
            {
                IEnumerator<IECProperty> propertyEnum = inst.ClassDefinition.GetEnumerator();
                while (propertyEnum.MoveNext())
                {
                    if (propertyEnum.Current.Name == "Volume")
                    {
                        IECPropertyValue propertyValue = inst.GetPropertyValue(propertyEnum.Current.Name);
                        ret = propertyValue.DoubleValue / Math.Pow(GeneralHelpers.UorToMeters, 3);
                        break;
                    }
                }
            }
            return ret;
        }
    }
}
